<?php

namespace app\cdc\logic\admin;

use app\common\model\mysql\RuleModel;
use app\common\logic\BaseLogic;
use think\facade\Db;

class RuleLogic extends BaseLogic
{
    public function index($request)
    {
        $param = $request->param();
        $system_id = $param['system_id'] ?? 1;
        $list = '';
        $rule_list = RuleModel::getList(['system_id' => $system_id], ['id', 'name', 'route', 'route_mode', 'parent_id', 'is_menu', 'status', 'system_id'], [], ['sort' => 'ASC']);

        if (!empty($rule_list)) {
            $rule_list = getTree(objToArray($rule_list));
            $list = self::getRuleHtml($rule_list);
        }


        return view('Rule/rule', compact('list', 'system_id'));
    }

    public function create($request)
    {
        $param = $request->param();
        $system_id = $param['system_id'];
        $ruleList = RuleModel::getList(['status' => '1', 'is_menu' => '1', 'system_id' => $system_id], ['id', 'name', 'parent_id'], [], ['sort' => 'ASC']);
        $list = [];
        if (!empty($ruleList[0])) {
            $ruleList = getTree($ruleList->toArray());
            $list = arrayToObj(self::getRuleList($ruleList));
        }
        return view('Rule/rule_add', compact('list', 'system_id'));
    }

    public function save($request)
    {
        $param = $request->param();
        $inputData = [
            'name' => $param['name'],
            'route' => $param['route'],
            'route_mode' => $param['route_mode'],
            'parent_id' => $param['parent_id'],
            'icon' => $param['icon'],
            'remark' => $param['remark'],
            'is_menu' => $param['is_menu'],
            'status' => $param['status'],
            'system_id' => $param['system_id']
        ];
        try {
            RuleModel::addData($inputData);
        } catch (\Exception $e) {
            return $this->opera(['content' => '添加权限规则失败', 'outcome' => $e->getMessage()])->responseError('保存失败');
        }
        return $this->opera(['content' => '添加权限规则成功'])->responseSuccess('保存成功');
    }

    public function edit($request, $id)
    {
        $param = $request->param();
        $system_id = $param['system_id'];
        $rule_list = RuleModel::getList(['status' => '1', 'is_menu' => '1', 'system_id' => $system_id], ['id', 'name', 'parent_id'], [], ['sort' => 'ASC']);
        if (!empty($rule_list[0])) {
            $rule_list = getTree(objToArray($rule_list));
            $list = arrayToObj(self::getRuleList($rule_list));
        }

        $info = RuleModel::getOne(['id' => $id]);
        return view('Rule/rule_edit', compact('info', 'list', 'system_id'));
    }

    public function update($request, $id)
    {
        $param = $request->param();
        $inputData = [
            'name' => $param['name'],
            'route' => $param['route'],
            'route_mode' => $param['route_mode'],
            'parent_id' => $param['parent_id'],
            'icon' => $param['icon'],
            'remark' => $param['remark'],
            'is_menu' => $param['is_menu'],
            'status' => $param['status'],
            'system_id' => $param['system_id']
        ];

        try {
            RuleModel::editData($inputData, ['id' => $id]);
        } catch (\Exception $e) {
            return $this->opera(['content' => '编辑权限规则失败', 'outcome' => $e->getMessage()])->responseError('保存失败');
        }
        return $this->opera(['content' => '编辑权限规则成功'])->responseSuccess('保存成功');
    }

    public function delete($request, $id)
    {
        try {
            RuleModel::deleteData(['id' => $id]);
        } catch (\Exception $e) {
            return $this->opera(['content' => '删除权限规则失败', 'outcome' => $e->getMessage()])->responseError('删除失败');
        }
        return $this->opera(['content' => '删除权限规则成功'])->responseSuccess('删除成功');
    }

    public function resort($request)
    {
        $rule_ids = json_decode($request->param('rule_ids'), true);
        $rule_list = $this->resortRule($rule_ids);

        $ids = array_column($rule_list, 'id');
        $ids = implode(',', $ids);

        // 更新sort 和 parent_id 两个字段
        $table_name = RuleModel::getTable();
        $sql = "UPDATE {$table_name} set ";
        $sort_sql = "sort = CASE id ";
        $parent_sql = "parent_id = CASE id ";
        foreach ($rule_list as $key => $rule) {
            $sort_sql .= "WHEN {$rule['id']} THEN {$key} ";
            $parent_sql .= "WHEN {$rule['id']} THEN {$rule['parent_id']} ";
        }
        $sort_sql .= 'END, ';
        $parent_sql .= 'END ';
        $sql .= $sort_sql . $parent_sql . "WHERE id IN ($ids)";

        try {
            Db::execute($sql);
            return $this->opera(['content' => '修改权限规则顺序成功'])->responseSuccess('保存成功');
        } catch (\Exception $e) {
            return $this->opera(['content' => '修改权限规则顺序失败', 'outcome' => $e->getMessage()])->responseError('保存失败');
        }
    }

    public function status($request, $id)
    {
        $param = $request->param();
        $inputData = [
            'status' => $param['status']
        ];
        try {
            RuleModel::editData($inputData, ['id' => $id]);
            return $this->opera(['content' => '编辑权限规则状态成功'])->responseSuccess('保存成功');
        } catch (\Exception $e) {
            return $this->opera(['content' => '编辑权限规则状态失败', 'outcome' => $e->getMessage()])->responseError('保存失败');
        }
    }

    /**
     * @param $rule_list
     * @param array $combination
     * @param int $parent_id
     * @return array
     */
    protected function resortRule($rule_list, $combination = [], $parent_id = 0)
    {
        foreach ($rule_list as $key => $rule) {
            $combination[] = ["id" => $rule["id"], "parent_id" => $parent_id];
            if (!empty($rule["children"])) {
                $children_node = self::resortRule($rule["children"], [], $rule["id"]);
                foreach ($children_node as $val) {
                    $combination[] = ["id" => $val["id"], "parent_id" => $val["parent_id"]];
                }
            }
        }
        return $combination;
    }


    /**
     * @param $rule_list
     * @param array $combination
     * @param int $deep
     * @param int $is_final
     * @return array
     */
    protected function getRuleList($rule_list, $combination = [], $deep = 0, $is_final = 0)
    {
        // 查看处理的数组有多少个
        $rule_count = count($rule_list);
        foreach ($rule_list as $key => $rule) {
            // 当前的位置（1开头）
            $current_num = $key + 1;

            $level_name = '';
            if (!empty($deep)) {
                for ($i = 0; $i < $deep; $i++) {
                    // 判断是否为最后一层
                    if ($i == $deep - 1) {
                        // 判断是否为最后一层的最后一个
                        if ($current_num == $rule_count) {
                            $level_name .= '└&nbsp;';
                        } else {
                            $level_name .= '├&nbsp;';
                        }
                    } else {
                        // 如果是第一层的最后一个 的子元素 的 第一个
                        if ($is_final == 1 && $i == 0) {
                            $level_name .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
                        } else {
                            $level_name .= '│&nbsp;';
                        }
                    }
                }
            }

            $rule['level_name'] = $level_name . $rule['name'];
            $rule['deep'] = $is_final;

            // 删除掉 sub_menu 键的元素
            $combination[] = array_diff_key($rule, ['sub_menu' => 1]);
            if (!empty($rule['sub_item'])) {
                // 判断是否第一层的最后一个
                if ($deep == 1 && $current_num == $rule_count) {
                    $is_final = 1;
                }
                $deep_tmp = $deep;
                $combination = self::getRuleList($rule['sub_item'], $combination, $deep_tmp + 1, $is_final);
            }
        }
        return $combination;
    }

    /**
     * @param $rule_list
     * @param bool $is_outer
     * @return string
     */
    protected function getRuleHtml($rule_list, $is_outer = true)
    {
        $rule_html = $is_outer == true ? "<ol class='dd-list'>" : "";

        // 编辑菜单属性
        foreach ($rule_list as $key => $rule) {

            $route = !empty($rule["route"]) ? "({$rule["route"]} | {$rule['route_mode']})" : "";
            $status_url = config('admin.app_host') . '/admin/rule/status/' . $rule['id'];
            $edit_url = config('admin.app_host') . '/admin/rule/' . $rule['id'] . '/edit' . '?system_id=' . $rule['system_id'];
            $delete_url = config('admin.app_host') . '/admin/rule/' . $rule['id'];

            $rule_html .= "<li class='dd-item nestable-menu-item' data-id='{$rule["id"]}'><div class='dd-handle nestable-full-width'><div style='display: inline-block'><span class='nestable-menu-name'>{$rule["name"]}</span> $route </div></div><div class='pull-right nestable-menu-btn'>";
            if ($rule['status'] == 1) {
                $rule_html .= "<button class='btn btn-info btn-outline btn-xs' type='button' onclick='change_status($(this),\"{$status_url}\")' data-status='1'><i class='fa fa-eye'></i>&nbsp;显示</button>&nbsp;&nbsp;";
            } else {
                $rule_html .= "<button class='btn btn-danger btn-outline btn-xs' type='button' onclick='change_status($(this),\"{$status_url}\")' data-status='0'><i class='fa fa-eye-slash'></i>&nbsp;隐藏</button>&nbsp;&nbsp;";
            }
            $rule_html .= "<button class='btn btn-info btn-xs' type='button' onclick='get_html($(this),\"{$edit_url}\")'><i class='fa fa-pencil'></i>&nbsp;编辑</button>&nbsp;&nbsp;<button class='btn btn-danger btn-xs' type='button' onclick='delete_form($(this),\"{$delete_url}\")'><i class='fa fa-trash'></i>&nbsp;删除</button></div>";

            // 判断是否存在子菜单,存在就添加 子菜单的 类名
            if (!empty($rule['sub_item'])) {
                $rule_html .= "<ol class='dd-list'>";
                // 回调子菜单
                $rule_html .= self::getRuleHtml($rule['sub_item'], false);
                $rule_html .= "</ol>";
            }
            $rule_html .= "</li>";
        }

        $rule_html .= $is_outer == true ? "</ol>" : "";

        return $rule_html;
    }
}